package semsearch;

import indexer.Indexer;
import indexer.ListeTermes;
import indexer.Term;
import java.io.File;
import static java.lang.Math.log;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
import utils.Constantes;

public class SemSearch {
	private static Connection connection;
	
    public static void main(String[] args) {
		// Initialisations
		PreparedStatement radicalInsertion = null;
		try {
			connection = Constantes.getConnetion();
			radicalInsertion = connection.prepareStatement (
					"INSERT INTO term (id, radical, CFW) VALUES (?, ?, ?)"
			);
		} catch (SQLException | ClassNotFoundException ex) {
			System.err.println("Impossible de se connecter à la base de données...");
			Logger.getLogger(SemSearch.class.getName()).log(Level.SEVERE, null, ex);
			
			System.exit(1);
		}
		
		System.out.println("Nettoyage de la base de données...");
		cleanDB();
		
		System.out.println("Récupération de la liste des fichiers...");
		String[] listeRessources = new File(Constantes.DOCS_PATH).list();
		
		// Pour chaque fichier, on lance un thread qui va l'indexer
		int idDocument = 1;
		ArrayList<Indexer> threads = new ArrayList<>();
		for (String fileName : listeRessources) {
			Indexer indexer = new Indexer(fileName, idDocument);
			indexer.start();
			threads.add(indexer);
			idDocument++;
		}
		
		for (Indexer t : threads) {
			try {
				t.join();
			} catch (InterruptedException ex) {
				Logger.getLogger(SemSearch.class.getName()).log(Level.INFO, null, ex);
			}
		}
		
		// On inscrit l'ensemble des termes récoltés en base
		System.out.println("Insertion de tous les termes...");
		int nbTermes = ListeTermes.getInstance().size();
		int nbDocuments = listeRessources.length;
		
		for (Term terme : ListeTermes.getInstance()) {
			System.out.println("    - terme " + terme.getIdBd() + "/" + nbTermes);
			
			double cfw = log(nbDocuments) - log(terme.getNbDocuments());
			
			try {
				radicalInsertion.setInt(1, terme.getIdBd());
				radicalInsertion.setString(2, terme.getRadical());
				radicalInsertion.setDouble(3, cfw);
				radicalInsertion.execute();
			} catch (SQLException ex) {
				System.err.println("Impossible d'insérer le terme " + terme + "...");
				Logger.getLogger(Indexer.class.getName()).log(Level.SEVERE, null, ex);
			}
		}
		
		// Calcul de la longueur normalisée des documents
		System.out.println("Calcul de la longueur normalisée des documents...");
		try {
			Statement stmt = connection.createStatement();
			
			// On récupère d'abord la longueur moyenne des documents
			ResultSet results = stmt.executeQuery("SELECT AVG(longueur) as avg FROM document");
			double moyenne = 1;
			if(results != null && results.next()){
				moyenne = results.getDouble("avg");
			}
			
			// On fait alors l'update en fonction de la longueur de chaque document
			stmt.executeUpdate("UPDATE document SET longueurNorme = longueur / " + moyenne);
		} catch (SQLException ex) {
			Logger.getLogger(SemSearch.class.getName()).log(Level.SEVERE, null, ex);
		}
		
		// Pondération des occurrences
		System.out.println("Pondération des occurrences...");
		try {
			Statement stmt = connection.createStatement();
			stmt.executeUpdate(
				"UPDATE occurence o, document d, term t " +
				"SET o.poids = ( t.CFW * o.frequence * (" + Constantes.K1 + " + 1) ) / " +
				"			   ( " + Constantes.K1 + " * ( (1-" + Constantes.b + ") " +
				"					+ (" + Constantes.b + " * d.longueurNorme) ) + o.frequence ) " +
				"WHERE o.id_document = d.id " +
				"  AND o.id_term = t.id"
			);
		} catch (SQLException ex) {
			Logger.getLogger(SemSearch.class.getName()).log(Level.SEVERE, null, ex);
		}
    }
    
	public static void cleanDB() {
		String requete = "TRUNCATE TABLE document";
		try {
			Statement stmt = connection.createStatement();
			stmt.executeUpdate(requete);
		} catch (SQLException e) {
			System.err.println("Impossible de vider la table document...");
			Logger.getLogger(Indexer.class.getName()).log(Level.SEVERE, null, e);
		}
		
		requete = "TRUNCATE TABLE occurence";
		try {
			Statement stmt = connection.createStatement();
			stmt.executeUpdate(requete);
		} catch (SQLException e) {
			System.err.println("Impossible de vider la table occurence...");
			Logger.getLogger(Indexer.class.getName()).log(Level.SEVERE, null, e);
		}
		
		requete = "TRUNCATE TABLE term";
		try {
			Statement stmt = connection.createStatement();
			stmt.executeUpdate(requete);
		} catch (SQLException e) {
			System.err.println("Impossible de vider la table term...");
			Logger.getLogger(Indexer.class.getName()).log(Level.SEVERE, null, e);
		}
	}
}
